/*
 * Copyright (C) 2017 zhouyou(478319399@qq.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.shuyihui.rxhttp.utils

import android.text.TextUtils
import android.util.Log
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject

object HttpLog {
    @JvmField
    var customTagPrefix = "RxEasyHttp_"

    @JvmField
    var allowD = true

    @JvmField
    var allowE = true

    @JvmField
    var allowI = true

    @JvmField
    var allowV = true
    var allowW = true
    var allowWtf = true
    private fun generateTag(caller: StackTraceElement): String {
        var tag = "%s.%s(L:%d)"
        var callerClazzName = caller.className
        callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1)
        tag = String.format(tag, callerClazzName, caller.methodName, caller.lineNumber)
        tag = if (TextUtils.isEmpty(customTagPrefix)) tag else customTagPrefix + ":" + tag
        return tag
    }

    var customLogger: CustomLogger? = null
    fun d(content: String?) {
        if (!allowD) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.d(tag, content)
        } else {
            Log.d(tag, content!!)
        }
    }

    val callerStackTraceElement: StackTraceElement
        get() = Thread.currentThread().stackTrace[4]

    fun d(content: String?, tr: Throwable?) {
        if (!allowD) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.d(tag, content, tr)
        } else {
            Log.d(tag, content, tr)
        }
    }

    fun e(content: String?) {
        if (!allowE) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.e(tag, content)
        } else {
            Log.e(tag, content!!)
        }
    }

    fun e(e: Exception) {
        if (!allowE) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.e(tag, e.message, e)
        } else {
            Log.e(tag, e.message, e)
        }
    }

    fun e(content: String?, tr: Throwable?) {
        if (!allowE) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.e(tag, content, tr)
        } else {
            Log.e(tag, content, tr)
        }
    }

    fun i(content: String?) {
        if (!allowI) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.i(tag, content)
        } else {
            Log.i(tag, content!!)
        }
    }

    @JvmStatic
    fun i(content: String?, tr: Throwable?) {
        if (!allowI) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.i(tag, content, tr)
        } else {
            Log.i(tag, content, tr)
        }
    }

    fun v(content: String?) {
        if (!allowV) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.v(tag, content)
        } else {
            Log.v(tag, content!!)
        }
    }

    fun v(content: String?, tr: Throwable?) {
        if (!allowV) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.v(tag, content, tr)
        } else {
            Log.v(tag, content, tr)
        }
    }

    fun w(content: String?) {
        if (!allowW) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.w(tag, content)
        } else {
            Log.w(tag, content!!)
        }
    }

    fun w(content: String?, tr: Throwable?) {
        if (!allowW) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.w(tag, content, tr)
        } else {
            Log.w(tag, content, tr)
        }
    }

    fun w(tr: Throwable?) {
        if (!allowW) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.w(tag, tr)
        } else {
            Log.w(tag, tr)
        }
    }

    fun wtf(content: String?) {
        if (!allowWtf) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.wtf(tag, content)
        } else {
            Log.wtf(tag, content)
        }
    }

    fun wtf(content: String?, tr: Throwable?) {
        if (!allowWtf) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.wtf(tag, content, tr)
        } else {
            Log.wtf(tag, content, tr)
        }
    }

    fun wtf(tr: Throwable?) {
        if (!allowWtf) return
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (customLogger != null) {
            customLogger!!.wtf(tag, tr)
        } else {
            Log.wtf(tag, tr!!)
        }
    }

    fun json(json: String) {
        val caller = callerStackTraceElement
        val tag = generateTag(caller)
        if (TextUtils.isEmpty(json)) {
            d("Empty/Null json content")
            return
        }
        try {
            if (json.startsWith("{")) {
                val jsonObject = JSONObject(json)
                val message = jsonObject.toString(4)
                d(message)
                return
            }
            if (json.startsWith("[")) {
                val jsonArray = JSONArray(json)
                val message = jsonArray.toString(4)
                d(message)
            }
        } catch (e: JSONException) {
            d(
                """
    ${e.cause!!.message}
    $json
    """.trimIndent()
            )
        }
    }

    interface CustomLogger {
        fun d(tag: String?, content: String?)
        fun d(tag: String?, content: String?, tr: Throwable?)
        fun e(tag: String?, content: String?)
        fun e(tag: String?, content: String?, tr: Throwable?)
        fun i(tag: String?, content: String?)
        fun i(tag: String?, content: String?, tr: Throwable?)
        fun v(tag: String?, content: String?)
        fun v(tag: String?, content: String?, tr: Throwable?)
        fun w(tag: String?, content: String?)
        fun w(tag: String?, content: String?, tr: Throwable?)
        fun w(tag: String?, tr: Throwable?)
        fun wtf(tag: String?, content: String?)
        fun wtf(tag: String?, content: String?, tr: Throwable?)
        fun wtf(tag: String?, tr: Throwable?)
    }
}